package sealedGenerator;

import java.io.File;
import java.util.ArrayList;
import java.util.Random;

import sealedGenerator.card.Card;


//contains a database of all cards in a set, as well as a method to generate a pack of cards from that set
public class Set {
	private ArrayList<Card> commons = new ArrayList<Card>();
	private ArrayList<Card> uncommons = new ArrayList<Card>();
	private ArrayList<Card> rares = new ArrayList<Card>();
	private ArrayList<Card> mythics = new ArrayList<Card>();
	private ArrayList<Card> basicLands = new ArrayList<Card>();
	private ArrayList<Card> specials = new ArrayList<Card>();
	private String name;
	private String expansionCode;
	private String packDistribution;
	/* packDistribution is a string that describes the amount of types of cards in a pack
	 * B = basic land
	 * C = common
	 * U = uncommon
	 * R = rare
	 * M = rare or mythic rare
	 * A = any rarity (no basic lands)
	 * S = special (timeshifted cards)
	 * 
	 * example of a m12 packDistribution:
	 * MUUUCCCCCCCCCCB
	 * 
	 * example of a cube distribution:
	 * AAAAAAAAAAAAAAA
	 */
	
	public Set (String name, String expansionCode, String packDistribution){
		this.name = name;
		this.expansionCode = expansionCode;
		this.packDistribution = packDistribution;
	}
	
	public Set(){}
	
	public void addCard(Card card) {
		switch(card.getRarity()) {
			case MYTHIC:
				mythics.add(card);
				break;
				
			case RARE:
				rares.add(card);
				break;
				
			case UNCOMMON:
				uncommons.add(card);
				break;
				
			case COMMON:
				commons.add(card);
				break;
				
			case LAND:
				basicLands.add(card);
				break;
		}
	}
	
	public ArrayList<Card> generateCubePacks(int numPacks) throws SetFormatException{
		String cubeDist = "";
		for (int i = 0; i < numPacks; i++){
			cubeDist += packDistribution;
		}
		return generatePack(cubeDist);
	}
	
	public ArrayList<Card> generatePack() throws SetFormatException{
		return generatePack(packDistribution);
	}
	
	private ArrayList<Card> generatePack(String packDistribution) throws SetFormatException{
		ArrayList<Card> pack = new ArrayList<Card>();
		ArrayList<Card> commonsLeft = (ArrayList<Card>) commons.clone();
		ArrayList<Card> uncommonsLeft = (ArrayList<Card>) uncommons.clone();
		ArrayList<Card> raresLeft = (ArrayList<Card>) rares.clone();
		ArrayList<Card> mythicsLeft = (ArrayList<Card>) mythics.clone();
		ArrayList<Card> specialsLeft = (ArrayList<Card>) specials.clone();
		
		try{
			for (int i = 0; i < packDistribution.length(); i++){
				Random r = new Random();
				
				switch (packDistribution.toUpperCase().charAt(i)){
					case 'B':
						pack.add(basicLands.get(r.nextInt(basicLands.size())));
						break;
					
					case 'C':
						pack.add(commonsLeft.remove(r.nextInt(commonsLeft.size())));
						break;
						
					case 'U':
						pack.add(uncommonsLeft.remove(r.nextInt(uncommonsLeft.size())));
						break;
					
					case 'R':
						pack.add(raresLeft.remove(r.nextInt(raresLeft.size())));
						break;
					
					case 'S':
						pack.add(specialsLeft.remove(r.nextInt(specialsLeft.size())));
						break;
					
					case 'M':
						if (Math.random() < ((double)mythics.size() / (double)(mythics.size() + 2*rares.size()) )){
							pack.add(mythicsLeft.remove(r.nextInt(mythicsLeft.size())));
						} else{
							pack.add(raresLeft.remove(r.nextInt(raresLeft.size())));
						}
						break;
						
					case 'A':
						int value = r.nextInt(commonsLeft.size() + uncommonsLeft.size() + raresLeft.size() + mythicsLeft.size());
						if (value < commonsLeft.size())
							pack.add(commonsLeft.remove(value));
						else if ((value -= commonsLeft.size()) < uncommonsLeft.size())
							pack.add(uncommonsLeft.remove(value));
						else if ((value -= uncommonsLeft.size()) < raresLeft.size())
							pack.add(raresLeft.remove(value));
						else if ((value -= raresLeft.size()) < mythicsLeft.size())
							pack.add(mythicsLeft.remove(value));
						else if ((value -= mythicsLeft.size()) < specialsLeft.size())
							pack.add(specialsLeft.remove(value));
						break;
						
					default:
						throw new SetFormatException("Invalid pack distribution string");
				}
			}
		} catch(IndexOutOfBoundsException oob){
			throw new SetFormatException("Set does not contain enough cards to generate a pack.");
		} catch(ArithmeticException ae){
			throw new SetFormatException("Set contains zero rares and zero mythics, yet has a set distribution string that contains rares/mythics.");
		}
		return pack;
	}

	public String listCards(){
		String ret = "Mythics:\n";
		for (Card c : mythics){
			ret += c + "\n";
		}
		ret += "\nRares:\n";
		for (Card c : rares){
			ret += c + "\n";
		}
		ret += "\nUncommons:\n";
		for (Card c : uncommons){
			ret += c + "\n";
		}
		ret += "\nCommons:\n";
		for (Card c : commons){
			ret += c + "\n";
		}
		if (specials.size() != 0){
			ret += "\nSpecials:\n";
			for (Card c : specials){
				ret += c + "\n";
			}
		}
		if (basicLands.size() != 0){
			ret += "\nBasic Lands:\n";
			for (Card c : basicLands){
				ret += c + "\n";
			}
		}
		return ret;
	}

	public String getExpansionCode() {return expansionCode;}
	public String getName(){return name;}
}